#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk
import threading
import time
import pyautogui
import cv2
import numpy as np
import json
import easyocr
import os
from typing import Dict, List, Tuple, Optional
from generals_enum import AVAILABLE_GENERALS, get_all_general_names, load_generals_from_directory

class UnifiedSmartRecognizer:
    """一体化智能武将管理系统 - 集成区域标定和识别功能"""
    
    def __init__(self):
        pyautogui.PAUSE = 0.1
        pyautogui.FAILSAFE = False
        
        # 获取分辨率信息
        self.logical_width, self.logical_height = pyautogui.size()
        screenshot = pyautogui.screenshot()
        self.physical_width, self.physical_height = screenshot.width, screenshot.height
        self.scale_x = self.physical_width / self.logical_width
        self.scale_y = self.physical_height / self.logical_height
        
        print(f"逻辑分辨率: {self.logical_width}x{self.logical_height}")
        print(f"物理分辨率: {self.physical_width}x{self.physical_height}")
        print(f"缩放比例: {self.scale_x:.1f}x{self.scale_y:.1f}")
        
        # 初始化OCR
        self.init_ocr()
        
        # 区域数据
        self.regions = {
            'camp': {'top_left': None, 'bottom_right': None, 'name': '营帐区域'},
            'battlefield': {'top_left': None, 'bottom_right': None, 'name': '上阵区域'},
            'hand': {'top_left': None, 'bottom_right': None, 'name': '手牌区域'}
        }
        
        # 尝试加载已有的区域标定数据
        self.load_region_calibration()
        
        # 加载武将列表
        self.load_general_list()
        
        # 识别结果存储
        self.region_generals = {
            'camp': [],
            'battlefield': [],
            'hand': []
        }
        
        # 选择的武将
        self.selected_generals = {
            'camp': set(),
            'battlefield': set(),
            'hand': set()
        }
        
        # 界面状态
        self.calibration_mode = False
        
        # 速度设置
        self.speed_setting = 1
        
        # 控制变量
        self.running = False
        
        # 创建GUI
        self.create_gui()
        
    def init_ocr(self):
        """初始化OCR"""
        try:
            self.ocr_reader = easyocr.Reader(['ch_sim', 'en'], gpu=False)
            print("✅ OCR初始化成功")
        except Exception as e:
            print(f"❌ OCR初始化失败: {e}")
            self.ocr_reader = None
            
    def load_region_calibration(self):
        """加载区域标定数据"""
        try:
            with open("region_calibration.json", "r", encoding="utf-8") as f:
                self.calibration_data = json.load(f)
            self.regions = self.calibration_data['regions']
            print(f"✅ 已加载区域标定数据")
        except Exception as e:
            print(f"⚠️ 未找到区域标定数据，将进入标定模式")
            self.calibration_data = None
            self.calibration_mode = True
            
    def load_general_list(self):
        """加载武将列表"""
        # 使用武将枚举中的数据
        self.available_generals = get_all_general_names()
        print(f"📋 从枚举加载了 {len(self.available_generals)} 个武将")
        
        # 验证与实际文件的一致性
        actual_generals = load_generals_from_directory("游戏资料/武将图片")
        print(f"📁 从目录加载了 {len(actual_generals)} 个武将文件")
        
        if len(actual_generals) > 0:
            # 如果实际文件存在，使用实际文件列表
            missing_in_enum = set(actual_generals) - set(self.available_generals)
            missing_files = set(self.available_generals) - set(actual_generals)
            
            if missing_in_enum:
                print(f"⚠️ 枚举中缺少的武将: {missing_in_enum}")
            if missing_files:
                print(f"⚠️ 文件中缺少的武将: {missing_files}")
                
            # 使用交集，确保枚举和文件都有的武将
            intersection = set(self.available_generals) & set(actual_generals)
            self.available_generals = sorted(list(intersection))
            print(f"🔗 交集后武将数量: {len(self.available_generals)}")
        else:
            print("⚠️ 未找到武将图片文件，使用枚举数据")
            
        print(f"✅ 已加载 {len(self.available_generals)} 个武将")
        if len(self.available_generals) > 0:
            print(f"武将列表: {self.available_generals[:10]}{'...' if len(self.available_generals) > 10 else ''}")
        else:
            print("❌ 武将列表为空！请检查枚举数据和文件目录")
            # 如果为空，至少加载枚举数据
            self.available_generals = get_all_general_names()
            print(f"🔧 已恢复使用枚举数据: {len(self.available_generals)} 个武将")
            
    def create_gui(self):
        """创建GUI界面"""
        self.root = tk.Tk()
        self.root.title("三国杀自走棋 - 一体化智能识别系统")
        self.root.geometry("1000x800")
        
        # 添加窗口拖动功能
        self.setup_window_drag()
        
        # 主标题
        title = tk.Label(self.root, text="一体化智能武将管理系统", 
                        font=("Arial", 16, "bold"))
        title.pack(pady=5)
        
        # 状态显示
        self.status_var = tk.StringVar()
        self.status_var.set("准备就绪")
        status_label = tk.Label(self.root, textvariable=self.status_var, 
                               fg="blue", font=("Arial", 12))
        status_label.pack(pady=3)
        
        # 创建界面切换按钮
        switch_frame = tk.Frame(self.root)
        switch_frame.pack(fill=tk.X, padx=10, pady=(5,0))
        
        self.calibration_btn = tk.Button(switch_frame, text="🔧 区域标定", 
                                       command=self.show_calibration_interface,
                                       bg="lightgreen", font=("Arial", 12, "bold"),
                                       width=15, height=2)
        self.calibration_btn.pack(side=tk.LEFT, padx=5)
        
        self.recognition_btn = tk.Button(switch_frame, text="🎯 智能识别", 
                                       command=self.show_recognition_interface,
                                       bg="lightblue", font=("Arial", 12, "bold"),
                                       width=15, height=2)
        self.recognition_btn.pack(side=tk.LEFT, padx=5)
        
        # 创建主内容区域
        self.main_content_frame = tk.Frame(self.root)
        self.main_content_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=(5,0))
        
        print("🔧 创建界面框架...")
        
        # 创建两个界面框架但不显示
        self.calibration_frame = tk.Frame(self.main_content_frame)
        self.recognition_frame = tk.Frame(self.main_content_frame)
        
        # 创建界面内容
        self.create_calibration_interface()
        print("✅ 区域标定界面已创建")
        
        self.create_recognition_interface()
        print("✅ 智能识别界面已创建")
        
        # 根据标定状态显示对应界面
        if self.calibration_mode:
            self.show_calibration_interface()
            print("🔧 显示区域标定界面")
        else:
            self.show_recognition_interface()
            print("🎯 显示智能识别界面")
            
        # 底部日志区域
        log_frame = tk.Frame(self.root)
        log_frame.pack(fill=tk.X, pady=(5,5), padx=10, side=tk.BOTTOM)
        
        tk.Label(log_frame, text="操作日志:").pack(anchor=tk.W)
        
        self.log_text = scrolledtext.ScrolledText(log_frame, height=4, width=120)
        self.log_text.pack(fill=tk.X)
        
    def show_calibration_interface(self):
        """显示区域标定界面"""
        # 隐藏识别界面，显示标定界面
        self.recognition_frame.pack_forget()
        self.calibration_frame.pack(fill=tk.BOTH, expand=True)
        
        # 更新按钮状态
        self.calibration_btn.config(bg="orange", state=tk.DISABLED)
        self.recognition_btn.config(bg="lightblue", state=tk.NORMAL)
        
        self.log("切换到区域标定界面")
        
    def show_recognition_interface(self):
        """显示智能识别界面"""
        # 隐藏标定界面，显示识别界面
        self.calibration_frame.pack_forget()
        self.recognition_frame.pack(fill=tk.BOTH, expand=True)
        
        # 更新按钮状态
        self.recognition_btn.config(bg="orange", state=tk.DISABLED)
        self.calibration_btn.config(bg="lightgreen", state=tk.NORMAL)
        
        self.log("切换到智能识别界面")
        
    def create_calibration_interface(self):
        """创建标定界面"""
        # 清空之前的内容
        for widget in self.calibration_frame.winfo_children():
            widget.destroy()
            
        # 说明文字
        instruction = tk.Label(self.calibration_frame, 
                              text="🎯 游戏区域标定 - 请依次标定三个区域的左上角和右下角坐标",
                              fg="darkblue", font=("Arial", 14, "bold"))
        instruction.pack(pady=15)
        
        # 创建滚动区域
        canvas = tk.Canvas(self.calibration_frame)
        scrollbar = tk.Scrollbar(self.calibration_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = tk.Frame(canvas)
        
        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        # 1. 营帐区域
        self.create_calibration_section(scrollable_frame, "营帐区域", "camp", 
                                      "招募武将的区域，通常在屏幕左侧", "lightgreen", 1)
        
        # 2. 上阵区域  
        self.create_calibration_section(scrollable_frame, "上阵区域", "battlefield",
                                      "战斗武将的区域，通常在屏幕中央", "lightyellow", 2)
        
        # 3. 手牌区域
        self.create_calibration_section(scrollable_frame, "手牌区域", "hand",
                                      "手牌武将的区域，通常在屏幕下方", "lightcyan", 3)
        
        # 底部操作按钮
        button_frame = tk.Frame(scrollable_frame)
        button_frame.pack(pady=20, fill="x")
        
        # 测试按钮
        test_btn = tk.Button(button_frame, text="🔍 测试区域截取", 
                           command=lambda: self.run_calibration_action(self.test_regions),
                           bg="orange", fg="white", font=("Arial", 11, "bold"),
                           width=18, height=2)
        test_btn.pack(side=tk.LEFT, padx=10)
        
        # 保存按钮
        save_btn = tk.Button(button_frame, text="💾 保存标定并切换到识别", 
                           command=lambda: self.run_calibration_action(self.save_calibration_and_switch),
                           bg="red", fg="white", font=("Arial", 11, "bold"),
                           width=25, height=2)
        save_btn.pack(side=tk.RIGHT, padx=10)
        
        # 打包滚动区域
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 更新状态显示
        self.update_calibration_status_display()
        
    def create_calibration_section(self, parent, name, region_type, description, color, index):
        """创建单个标定区域"""
        # 区域框架
        frame = tk.LabelFrame(parent, text=f"{index}. {name}",
                            font=("Arial", 12, "bold"), padx=15, pady=10)
        frame.pack(pady=10, fill="x", padx=20)
        
        # 描述文字
        desc_label = tk.Label(frame, text=description, 
                            fg="gray", font=("Arial", 10))
        desc_label.pack(pady=(0, 10))
        
        # 按钮框架
        btn_frame = tk.Frame(frame)
        btn_frame.pack(pady=5)
        
        # 左上角按钮
        left_btn = tk.Button(btn_frame, text=f"📍 标定{name}左上角", 
                           command=lambda: self.calibrate_point(region_type, 'top_left'),
                           bg=color, font=("Arial", 10, "bold"),
                           width=20, height=2)
        left_btn.pack(side=tk.LEFT, padx=5)
        
        # 右下角按钮  
        right_btn = tk.Button(btn_frame, text=f"📍 标定{name}右下角",
                            command=lambda: self.calibrate_point(region_type, 'bottom_right'), 
                            bg=color, font=("Arial", 10, "bold"),
                            width=20, height=2)
        right_btn.pack(side=tk.LEFT, padx=5)
        
        # 状态标签
        status_label = tk.Label(frame, text="❌ 未标定", fg="red", font=("Arial", 11))
        status_label.pack(pady=5)
        
        # 保存状态标签引用
        setattr(self, f"{region_type}_status", status_label)
        
    def create_recognition_interface(self):
        """创建识别界面"""
        # 速度设置
        speed_frame = tk.LabelFrame(self.recognition_frame, text="操作速度", padx=5, pady=5)
        speed_frame.pack(pady=5, fill="x", padx=15)
        
        self.speed_var = tk.IntVar(value=1)
        speed_row = tk.Frame(speed_frame)
        speed_row.pack()
        tk.Radiobutton(speed_row, text="正常速度", variable=self.speed_var, 
                      value=1, command=self.update_speed).pack(side=tk.LEFT, padx=10)
        tk.Radiobutton(speed_row, text="快速模式", variable=self.speed_var, 
                      value=2, command=self.update_speed).pack(side=tk.LEFT, padx=10)
                      
        # 主要内容区域
        main_frame = tk.Frame(self.recognition_frame)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 左侧操作面板
        left_frame = tk.Frame(main_frame, width=300)
        left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=5)
        left_frame.pack_propagate(False)
        
        # 区域识别按钮
        recognize_frame = tk.LabelFrame(left_frame, text="区域识别", padx=5, pady=5)
        recognize_frame.pack(fill="x", pady=5)
        
        tk.Button(recognize_frame, text="1. 识别营帐区域", 
                 command=lambda: self.run_action(lambda: self.recognize_region('camp')),
                 bg="lightgreen", width=20, height=1).pack(pady=2)
                 
        tk.Button(recognize_frame, text="2. 识别上阵区域", 
                 command=lambda: self.run_action(lambda: self.recognize_region('battlefield')),
                 bg="yellow", width=20, height=1).pack(pady=2)
                 
        tk.Button(recognize_frame, text="3. 识别手牌区域", 
                 command=lambda: self.run_action(lambda: self.recognize_region('hand')),
                 bg="lightblue", width=20, height=1).pack(pady=2)
                 
        tk.Button(recognize_frame, text="4. 识别所有区域", 
                 command=lambda: self.run_action(self.recognize_all_regions),
                 bg="orange", width=20, height=1).pack(pady=2)
        
        # 操作按钮
        operation_frame = tk.LabelFrame(left_frame, text="武将操作", padx=5, pady=5)
        operation_frame.pack(fill="x", pady=5)
        
        tk.Button(operation_frame, text="招募选中武将", 
                 command=lambda: self.run_action(self.recruit_selected),
                 bg="red", fg="white", width=20, height=1).pack(pady=2)
                 
        tk.Button(operation_frame, text="遣散选中武将", 
                 command=lambda: self.run_action(self.dismiss_selected),
                 bg="purple", fg="white", width=20, height=1).pack(pady=2)
                 
        tk.Button(operation_frame, text="上阵选中武将", 
                 command=lambda: self.run_action(self.deploy_selected),
                 bg="blue", fg="white", width=20, height=1).pack(pady=2)
                 
        tk.Button(operation_frame, text="停止所有操作", 
                 command=self.stop_all,
                 bg="gray", width=20, height=1).pack(pady=2)
        
        # 右侧面板
        right_frame = tk.Frame(main_frame)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5)
        
        # 武将选择面板
        select_frame = tk.LabelFrame(right_frame, text="选择要招募的武将", padx=5, pady=5)
        select_frame.pack(fill="both", expand=True, pady=(0, 5))
        
        # 全选/取消全选按钮
        select_btn_frame = tk.Frame(select_frame)
        select_btn_frame.pack(fill="x", pady=2)
        
        tk.Button(select_btn_frame, text="全选", command=self.select_all_generals,
                 bg="lightgreen", width=8).pack(side=tk.LEFT, padx=2)
        tk.Button(select_btn_frame, text="取消全选", command=self.deselect_all_generals,
                 bg="lightcoral", width=8).pack(side=tk.LEFT, padx=2)
        
        # 武将选择滚动区域
        select_canvas_frame = tk.Frame(select_frame, height=120)
        select_canvas_frame.pack(fill="both", expand=True, pady=2)
        select_canvas_frame.pack_propagate(False)
        
        self.select_canvas = tk.Canvas(select_canvas_frame, bg="white", highlightthickness=0)
        select_scrollbar = tk.Scrollbar(select_canvas_frame, orient="vertical", command=self.select_canvas.yview)
        self.select_scrollable = tk.Frame(self.select_canvas, bg="white")
        
        self.select_canvas.configure(yscrollcommand=select_scrollbar.set)
        self.select_canvas.pack(side="left", fill="both", expand=True)
        select_scrollbar.pack(side="right", fill="y")
        
        self.select_canvas.create_window((0, 0), window=self.select_scrollable, anchor="nw")
        
        # 创建武将选择复选框
        self.general_selection_vars = {}
        self.selected_general_names = set()
        
        self.create_general_selection_checkboxes()
        
        # 延迟刷新武将列表以确保界面已完全创建
        self.root.after(100, self.refresh_general_selection)
        
        # 创建三个区域的识别结果面板
        self.create_general_panels(right_frame)
        
    def create_general_panels(self, parent):
        """创建武将选择面板"""
        # 营帐区域武将
        self.create_region_panel(parent, 'camp', '营帐区域武将', 'lightgreen')
        
        # 上阵区域武将
        self.create_region_panel(parent, 'battlefield', '上阵区域武将', 'yellow')
        
        # 手牌区域武将
        self.create_region_panel(parent, 'hand', '手牌区域武将', 'lightblue')
        
    def create_region_panel(self, parent, region_type, title, color):
        """创建单个区域面板"""
        frame = tk.LabelFrame(parent, text=title, padx=5, pady=5)
        frame.pack(fill="x", pady=3)
        
        # 按钮框架
        btn_frame = tk.Frame(frame)
        btn_frame.pack(fill="x", pady=2)
        
        tk.Button(btn_frame, text="全选", 
                 command=lambda: self.select_all_in_region(region_type),
                 bg="lightgreen", width=8).pack(side=tk.LEFT, padx=2)
        tk.Button(btn_frame, text="取消", 
                 command=lambda: self.deselect_all_in_region(region_type),
                 bg="lightcoral", width=8).pack(side=tk.LEFT, padx=2)
        
        # 滚动区域
        canvas_frame = tk.Frame(frame, height=80)
        canvas_frame.pack(fill="x", pady=2)
        canvas_frame.pack_propagate(False)
        
        canvas = tk.Canvas(canvas_frame, height=80, bg="white", highlightthickness=0)
        scrollbar = tk.Scrollbar(canvas_frame, orient="vertical", command=canvas.yview)
        scrollable = tk.Frame(canvas, bg="white")
        
        canvas.configure(yscrollcommand=scrollbar.set)
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        canvas.create_window((0, 0), window=scrollable, anchor="nw")
        
        # 存储引用
        setattr(self, f"{region_type}_canvas", canvas)
        setattr(self, f"{region_type}_scrollable", scrollable)
        setattr(self, f"{region_type}_vars", {})
        
        # 初始提示
        tk.Label(scrollable, text="请先识别该区域", fg="gray", bg="white").pack(pady=20)
        
    def setup_window_drag(self):
        """设置窗口拖动功能"""
        def start_move(event):
            self.root.x = event.x
            self.root.y = event.y
            
        def stop_move(event):
            self.root.x = None
            self.root.y = None
            
        def do_move(event):
            if hasattr(self.root, 'x') and self.root.x is not None:
                deltax = event.x - self.root.x
                deltay = event.y - self.root.y
                x = self.root.winfo_x() + deltax
                y = self.root.winfo_y() + deltay
                self.root.geometry(f"+{x}+{y}")
        
        self.root.bind('<Button-1>', start_move)
        self.root.bind('<ButtonRelease-1>', stop_move)
        self.root.bind('<B1-Motion>', do_move)
        
    def create_general_selection_checkboxes(self):
        """创建武将选择复选框"""
        # 清除现有内容
        for widget in self.select_scrollable.winfo_children():
            widget.destroy()
            
        if not self.available_generals:
            tk.Label(self.select_scrollable, text="未加载武将数据", 
                    fg="gray", bg="white").pack(pady=20)
            return
            
        # 创建复选框，按4列排列
        cols = 4
        for i, general_name in enumerate(self.available_generals):
            var = tk.BooleanVar()
            self.general_selection_vars[general_name] = var
            
            cb = tk.Checkbutton(self.select_scrollable, text=general_name, 
                               variable=var, bg="white",
                               command=lambda g=general_name: self.toggle_general_selection_main(g))
            
            row = i // cols
            col = i % cols
            cb.grid(row=row, column=col, sticky="w", padx=5, pady=2)
            
        # 更新滚动区域
        self.select_scrollable.update_idletasks()
        self.select_canvas.configure(scrollregion=self.select_canvas.bbox("all"))
        
    def refresh_general_selection(self):
        """刷新武将选择列表显示"""
        print(f"🔄 刷新武将选择列表，当前武将数量: {len(self.available_generals)}")
        if hasattr(self, 'select_scrollable'):
            self.create_general_selection_checkboxes()
        
    def toggle_general_selection_main(self, general_name):
        """切换主武将选择状态"""
        if self.general_selection_vars[general_name].get():
            self.selected_general_names.add(general_name)
        else:
            self.selected_general_names.discard(general_name)
            
        self.log(f"当前选择武将: {len(self.selected_general_names)} 个")
        
    def select_all_generals(self):
        """全选武将"""
        for general_name, var in self.general_selection_vars.items():
            var.set(True)
            self.selected_general_names.add(general_name)
        self.log(f"已全选 {len(self.selected_general_names)} 个武将")
        
    def deselect_all_generals(self):
        """取消全选武将"""
        for general_name, var in self.general_selection_vars.items():
            var.set(False)
        self.selected_general_names.clear()
        self.log("已取消所有武将选择")
        
    def log(self, message):
        """输出日志"""
        timestamp = time.strftime("%H:%M:%S")
        log_msg = f"[{timestamp}] {message}\n"
        print(log_msg.strip())
        try:
            self.log_text.insert(tk.END, log_msg)
            self.log_text.see(tk.END)
        except:
            pass
            
    def run_action(self, action):
        """在线程中运行识别操作"""
        threading.Thread(target=action, daemon=True).start()
        
    def run_calibration_action(self, action):
        """在线程中运行标定操作"""
        threading.Thread(target=action, daemon=True).start()
        
    def calibrate_point(self, region_type, point_type):
        """标定区域的一个点"""
        region_name = self.regions[region_type]['name']
        point_name = "左上角" if point_type == 'top_left' else "右下角"
        
        self.log(f"开始标定{region_name}{point_name}")
        self.status_var.set(f"标定{region_name}{point_name}中...")
        
        # 开始5秒倒计时
        self.start_countdown(region_type, point_type, 5)
        
    def start_countdown(self, region_type, point_type, countdown):
        """开始倒计时标定"""
        region_name = self.regions[region_type]['name']
        point_name = "左上角" if point_type == 'top_left' else "右下角"
        
        if countdown > 0:
            self.log(f"倒计时: {countdown} 秒 - 请将鼠标移动到{region_name}{point_name}")
            self.status_var.set(f"倒计时: {countdown} 秒 - 标定{region_name}{point_name}")
            
            # 使用after方法在1秒后继续倒计时，不会阻塞界面
            self.root.after(1000, lambda: self.start_countdown(region_type, point_type, countdown - 1))
        else:
            # 倒计时结束，获取鼠标位置
            self.finish_calibration(region_type, point_type)
    
    def finish_calibration(self, region_type, point_type):
        """完成标定，获取鼠标位置"""
        region_name = self.regions[region_type]['name']
        point_name = "左上角" if point_type == 'top_left' else "右下角"
        
        # 获取当前鼠标位置
        x, y = pyautogui.position()
        self.regions[region_type][point_type] = {'x': x, 'y': y}
        
        self.log(f"✅ {region_name}{point_name}标定完成: ({x}, {y})")
        self.status_var.set("标定完成")
        
        # 更新状态显示
        self.update_calibration_status_display()
        
    def update_calibration_status_display(self):
        """更新标定状态显示"""
        for region_type, status_label in [
            ('camp', self.camp_status),
            ('battlefield', self.battle_status), 
            ('hand', self.hand_status)
        ]:
            region = self.regions[region_type]
            if region['top_left'] and region['bottom_right']:
                status_label.config(text="✅ 已完成标定", fg="green")
            elif region['top_left'] or region['bottom_right']:
                status_label.config(text="⚠️ 部分完成", fg="orange")
            else:
                status_label.config(text="❌ 未标定", fg="red")
                
    def test_regions(self):
        """测试区域截取"""
        self.log("=== 开始测试区域截取 ===")
        self.status_var.set("测试截取中...")
        
        screenshot = pyautogui.screenshot()
        screenshot_cv = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
        
        for region_type, region in self.regions.items():
            if not (region['top_left'] and region['bottom_right']):
                self.log(f"⚠️ {region['name']}未完成标定，跳过")
                continue
                
            # 转换为物理坐标
            left = int(region['top_left']['x'] * self.scale_x)
            top = int(region['top_left']['y'] * self.scale_y)
            right = int(region['bottom_right']['x'] * self.scale_x)
            bottom = int(region['bottom_right']['y'] * self.scale_y)
            
            # 截取区域
            try:
                region_img = screenshot_cv[top:bottom, left:right]
                filename = f"{region_type}_region_test.png"
                cv2.imwrite(filename, region_img)
                
                width = right - left
                height = bottom - top
                self.log(f"✅ {region['name']}截取成功: {filename} ({width}x{height})")
                
            except Exception as e:
                self.log(f"❌ {region['name']}截取失败: {e}")
                
        self.status_var.set("测试完成")
                
    def save_calibration_and_switch(self):
        """保存标定结果并切换到识别界面"""
        # 检查是否所有区域都已标定
        incomplete_regions = []
        for region_type, region in self.regions.items():
            if not (region['top_left'] and region['bottom_right']):
                incomplete_regions.append(region['name'])
                
        if incomplete_regions:
            messagebox.showwarning("标定未完成", f"以下区域未完成标定:\n" + "\n".join(incomplete_regions))
            return
            
        # 保存到文件
        calibration_data = {
            'screen_resolution': f"{self.logical_width}x{self.logical_height}",
            'physical_resolution': f"{self.physical_width}x{self.physical_height}",
            'scale': {'x': self.scale_x, 'y': self.scale_y},
            'regions': self.regions,
            'timestamp': time.strftime("%Y-%m-%d %H:%M:%S")
        }
        
        try:
            with open("region_calibration.json", "w", encoding="utf-8") as f:
                json.dump(calibration_data, f, indent=2, ensure_ascii=False)
                
            self.log("✅ 标定结果已保存到 region_calibration.json")
            self.calibration_data = calibration_data
            self.calibration_mode = False
            
            # 切换到识别界面
            self.show_recognition_interface()
            self.status_var.set("标定完成，可以开始识别")
            
            messagebox.showinfo("保存成功", "区域标定结果已保存，已切换到识别界面!")
            
        except Exception as e:
            self.log(f"❌ 保存失败: {e}")
            messagebox.showerror("保存失败", f"保存标定结果时出错: {e}")
            
    def update_speed(self):
        """更新速度设置"""
        self.speed_setting = self.speed_var.get()
        speed_text = "快速模式" if self.speed_setting == 2 else "正常速度"
        self.log(f"操作速度设置: {speed_text}")
        
    def get_speed_delays(self):
        """根据速度设置获取延时时间"""
        if self.speed_setting == 2:  # 快速模式
            return {
                'move_duration': 0.2,
                'click_delay': 0.1,
                'drag_duration': 0.4,
                'between_actions': 1.0
            }
        else:  # 正常速度
            return {
                'move_duration': 0.3,
                'click_delay': 0.2,
                'drag_duration': 0.8,
                'between_actions': 2.0
            }
            
    def recognize_region(self, region_type):
        """识别指定区域的武将"""
        if not self.regions or region_type not in self.regions:
            messagebox.showwarning("警告", "请先完成区域标定")
            return
            
        region = self.regions[region_type]
        if not (region.get('top_left') and region.get('bottom_right')):
            self.log(f"❌ {region['name']}区域标定不完整")
            return
            
        self.log(f"=== 开始识别{region['name']} ===")
        self.status_var.set(f"识别{region['name']}中...")
        
        try:
            # 截取区域
            screenshot = pyautogui.screenshot()
            screenshot_cv = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
            
            # 转换为物理坐标
            left = int(region['top_left']['x'] * self.scale_x)
            top = int(region['top_left']['y'] * self.scale_y)
            right = int(region['bottom_right']['x'] * self.scale_x)
            bottom = int(region['bottom_right']['y'] * self.scale_y)
            
            region_img = screenshot_cv[top:bottom, left:right]
            
            # 保存调试图片
            debug_filename = f"{region_type}_region_debug.png"
            cv2.imwrite(debug_filename, region_img)
            
            # OCR识别
            if self.ocr_reader is None:
                self.log("❌ OCR未初始化")
                return
                
            results = self.ocr_reader.readtext(region_img)
            
            # 解析OCR结果，匹配武将名称
            region_generals = []
            
            for (bbox, text, confidence) in results:
                if confidence < 0.5:  # 置信度太低，跳过
                    continue
                    
                # 在武将列表中查找匹配的武将
                for general_name in self.available_generals:
                    if general_name in text or text in general_name:
                        # 计算武将在屏幕中的绝对坐标
                        bbox_center_x = (bbox[0][0] + bbox[2][0]) // 2
                        bbox_center_y = (bbox[0][1] + bbox[2][1]) // 2
                        
                        # 转换为逻辑坐标
                        screen_x = region['top_left']['x'] + int(bbox_center_x / self.scale_x)
                        screen_y = region['top_left']['y'] + int(bbox_center_y / self.scale_y)
                        
                        region_generals.append({
                            'name': general_name,
                            'text': text,
                            'confidence': confidence,
                            'screen_pos': (screen_x, screen_y),
                            'region_pos': (bbox_center_x, bbox_center_y),
                            'bbox': bbox
                        })
                        
                        self.log(f"发现武将: {general_name} 在 ({screen_x}, {screen_y}) 置信度: {confidence:.2f}")
                        break
                        
            # 存储识别结果
            self.region_generals[region_type] = region_generals
            
            self.log(f"✅ {region['name']}识别完成，发现 {len(region_generals)} 个武将")
            self.status_var.set(f"{region['name']}识别完成: {len(region_generals)}个武将")
            
            # 更新界面显示
            self.update_region_display(region_type)
            
        except Exception as e:
            self.log(f"❌ {region['name']}识别失败: {e}")
            self.status_var.set("识别失败")
            
    def recognize_all_regions(self):
        """识别所有区域"""
        self.log("=== 开始识别所有区域 ===")
        for region_type in ['camp', 'battlefield', 'hand']:
            self.recognize_region(region_type)
            time.sleep(0.5)  # 短暂延时
        self.log("✅ 所有区域识别完成")
        
    def update_region_display(self, region_type):
        """更新区域显示"""
        canvas = getattr(self, f"{region_type}_canvas")
        scrollable = getattr(self, f"{region_type}_scrollable")
        
        # 清除现有内容
        for widget in scrollable.winfo_children():
            widget.destroy()
            
        # 创建新的复选框
        generals = self.region_generals[region_type]
        vars_dict = getattr(self, f"{region_type}_vars")
        vars_dict.clear()
        
        if not generals:
            tk.Label(scrollable, text="未识别到武将", fg="gray", bg="white").pack(pady=10)
        else:
            cols = 4  # 每行4个
            for i, general in enumerate(generals):
                var = tk.BooleanVar()
                vars_dict[general['name']] = var
                cb = tk.Checkbutton(scrollable, text=f"{general['name']}", 
                                   variable=var, bg="white",
                                   command=lambda g=general['name'], r=region_type, v=var: 
                                   self.toggle_general_selection(r, g, v))
                row = i // cols
                col = i % cols
                cb.grid(row=row, column=col, sticky="w", padx=5, pady=2)
                
        # 更新滚动区域
        scrollable.update_idletasks()
        canvas.create_window((0, 0), window=scrollable, anchor="nw")
        canvas.configure(scrollregion=canvas.bbox("all"))
        
    def toggle_general_selection(self, region_type, general_name, var):
        """切换武将选择状态"""
        if var.get():
            self.selected_generals[region_type].add(general_name)
        else:
            self.selected_generals[region_type].discard(general_name)
            
        total_selected = sum(len(s) for s in self.selected_generals.values())
        self.log(f"当前选择武将总数: {total_selected}")
        
    def select_all_in_region(self, region_type):
        """选中区域内所有武将"""
        vars_dict = getattr(self, f"{region_type}_vars")
        for general_name, var in vars_dict.items():
            var.set(True)
            self.selected_generals[region_type].add(general_name)
        self.log(f"全选{region_type}区域 {len(vars_dict)} 个武将")
        
    def deselect_all_in_region(self, region_type):
        """取消选中区域内所有武将"""
        vars_dict = getattr(self, f"{region_type}_vars")
        for general_name, var in vars_dict.items():
            var.set(False)
        self.selected_generals[region_type].clear()
        self.log(f"取消选中{region_type}区域所有武将")
        
    def recruit_selected(self):
        """招募选中的武将到手牌"""
        if not self.selected_general_names:
            messagebox.showwarning("警告", "请先在武将选择列表中选择要招募的武将")
            return
            
        if not self.region_generals['camp']:
            messagebox.showwarning("警告", "请先识别营帐区域以获取可招募的武将")
            return
            
        self.log("=== 开始招募操作 ===")
        self.status_var.set("招募中...")
        
        # 激活游戏窗口
        self.activate_game_window()
        
        # 获取速度设置
        delays = self.get_speed_delays()
        
        recruited_count = 0
        
        # 获取手牌区域的中心位置
        hand_region = self.regions.get('hand')
        if not hand_region:
            self.log("❌ 未找到手牌区域标定")
            return
            
        hand_center_x = (hand_region['top_left']['x'] + hand_region['bottom_right']['x']) // 2
        hand_center_y = (hand_region['top_left']['y'] + hand_region['bottom_right']['y']) // 2
        
        for general in self.region_generals['camp']:
            # 检查这个武将是否在用户选择的武将列表中
            if general['name'] not in self.selected_general_names:
                continue
                
            self.log(f"招募武将: {general['name']}")
            
            from_x, from_y = general['screen_pos']
            to_x, to_y = hand_center_x, hand_center_y
            
            # 执行拖拽操作
            self.perform_drag_operation(from_x, from_y, to_x, to_y, delays)
            
            recruited_count += 1
            time.sleep(delays['between_actions'])
            
        self.log(f"✅ 招募完成，共招募 {recruited_count} 个武将")
        self.status_var.set("招募完成")
        
    def dismiss_selected(self):
        """遣散选中的手牌武将到营帐"""
        if not self.selected_generals['hand']:
            messagebox.showwarning("警告", "请先在手牌区域识别结果中选择要遣散的武将")
            return
            
        self.log("=== 开始遣散操作 ===")
        self.status_var.set("遣散中...")
        
        # 激活游戏窗口
        self.activate_game_window()
        
        # 获取速度设置
        delays = self.get_speed_delays()
        
        dismissed_count = 0
        
        # 获取营帐区域的中心位置
        camp_region = self.regions.get('camp')
        if not camp_region:
            self.log("❌ 未找到营帐区域标定")
            return
            
        camp_center_x = (camp_region['top_left']['x'] + camp_region['bottom_right']['x']) // 2
        camp_center_y = (camp_region['top_left']['y'] + camp_region['bottom_right']['y']) // 2
        
        for general in self.region_generals['hand']:
            if general['name'] not in self.selected_generals['hand']:
                continue
                
            self.log(f"遣散武将: {general['name']}")
            
            from_x, from_y = general['screen_pos']
            to_x, to_y = camp_center_x, camp_center_y
            
            # 执行拖拽操作
            self.perform_drag_operation(from_x, from_y, to_x, to_y, delays)
            
            dismissed_count += 1
            time.sleep(delays['between_actions'])
            
        self.log(f"✅ 遣散完成，共遣散 {dismissed_count} 个武将")
        self.status_var.set("遣散完成")
        
    def deploy_selected(self):
        """上阵选中的手牌武将"""
        if not self.selected_generals['hand']:
            messagebox.showwarning("警告", "请先在手牌区域识别结果中选择要上阵的武将")
            return
            
        self.log("=== 开始上阵操作 ===")
        self.status_var.set("上阵中...")
        
        # 激活游戏窗口
        self.activate_game_window()
        
        # 获取速度设置
        delays = self.get_speed_delays()
        
        deployed_count = 0
        
        # 获取上阵区域的位置
        battlefield_region = self.regions.get('battlefield')
        if not battlefield_region:
            self.log("❌ 未找到上阵区域标定")
            return
            
        battlefield_center_x = (battlefield_region['top_left']['x'] + battlefield_region['bottom_right']['x']) // 2
        battlefield_center_y = (battlefield_region['top_left']['y'] + battlefield_region['bottom_right']['y']) // 2
        
        for general in self.region_generals['hand']:
            if general['name'] not in self.selected_generals['hand']:
                continue
                
            self.log(f"上阵武将: {general['name']}")
            
            from_x, from_y = general['screen_pos']
            # 为每个武将分配不同的上阵位置
            offset = deployed_count * 60  # 每个武将间隔60像素
            to_x = battlefield_center_x + offset
            to_y = battlefield_center_y
            
            # 执行拖拽操作
            self.perform_drag_operation(from_x, from_y, to_x, to_y, delays)
            
            deployed_count += 1
            time.sleep(delays['between_actions'])
            
        self.log(f"✅ 上阵完成，共上阵 {deployed_count} 个武将")
        self.status_var.set("上阵完成")
        
    def perform_drag_operation(self, from_x, from_y, to_x, to_y, delays):
        """执行拖拽操作"""
        try:
            self.log(f"拖拽: ({from_x}, {from_y}) → ({to_x}, {to_y})")
            
            # 移动到起点
            pyautogui.moveTo(from_x, from_y, duration=delays['move_duration'])
            time.sleep(delays['click_delay'])
            
            # 按下鼠标
            pyautogui.mouseDown(button='left')
            time.sleep(delays['click_delay'])
            
            # 拖拽到目标位置
            pyautogui.moveTo(to_x, to_y, duration=delays['drag_duration'])
            time.sleep(delays['click_delay'])
            
            # 释放鼠标
            pyautogui.mouseUp(button='left')
            
        except Exception as e:
            self.log(f"❌ 拖拽操作失败: {e}")
            
    def activate_game_window(self):
        """激活游戏窗口获得焦点"""
        self.log("激活游戏窗口...")
        center_x = self.logical_width // 2
        center_y = self.logical_height // 2
        
        pyautogui.moveTo(center_x, center_y, duration=0.2)
        time.sleep(0.1)
        pyautogui.click()
        time.sleep(0.5)
        
    def stop_all(self):
        """停止所有操作"""
        self.running = False
        self.log("停止所有操作")
        self.status_var.set("已停止")
        
    def run(self):
        """运行程序"""
        self.log("一体化智能识别器已启动")
        if self.calibration_mode:
            self.log("⚠️ 检测到未标定，请先在 '区域标定' 选项卡中完成标定")
        else:
            self.log("✅ 已加载区域标定数据，可以在 '智能识别' 选项卡中开始识别")
        self.root.mainloop()

if __name__ == "__main__":
    recognizer = UnifiedSmartRecognizer()
    recognizer.run()